#ifndef _ADLER32_H_
#define _ADLER32_H_

/*
	A = 1 + D1 + D2 + ... + Dn (mod 65521)
	B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
		= n*D1 + (n-1)*D2 + (n-2)*D3 + ... + Dn + n (mod 65521)

	Adler-32(D) = B * 65536 + A
*/
class Adler32
{
	public:
		static unsigned int Compute(const unsigned char *data, unsigned int bytes)
		{
			const unsigned int MOD_ADLER = 65521;	// the largest prime number smaller than 2^16
			unsigned int checksum = 0, sum_a = 1, sum_b = 0;
			if((bytes > 0) && (data != NULL))
			{
				for(unsigned int i = 0; i < bytes; i++)
				{
					sum_a = (sum_a + data[i]) % MOD_ADLER;
					sum_b = (sum_b + sum_a) % MOD_ADLER;
				}
				checksum = (sum_b << 16) | sum_a;
			}
			return checksum;
		}

		static bool Check(const unsigned char *data, unsigned int bytes, unsigned int checksum)
		{
			return (checksum == Compute(data, bytes));
		}
};

#endif	// _ADLER32_H_